package com.mall.common.service.impl;

import java.io.IOException;
import java.io.StringReader;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import com.mall.common.dao.MessageSendDao;
import com.mall.common.domain.content.SmsMessageDomain;
import com.mall.common.enums.MessageStatus;
import com.mall.common.enums.MessageType;
import com.mall.common.exception.NoticeException;
import com.mall.common.hibernate.Finder;
import com.mall.common.service.MessageSendService;
import com.mall.common.service.TemplateService;
import com.mall.common.util.DateHelper;
import com.mall.common.util.PropertiesHelper;
import com.mall.common.util.SerialNumberUtil;
import com.mall.common.util.VerifyUtil;

import freemarker.template.Configuration;
import freemarker.template.Template;
/**
 * 短信
 */
@Service
@Transactional
public class MessageSendServiceImpl extends BaseServiceImpl<SmsMessageDomain, Long> implements MessageSendService {
	private static final Long CAPTCHA_MOBILE_LIMIT = 10L;
	private static final Long CAPTCHA_IP_LIMIT = 20L;
	
	@Resource private FreeMarkerConfigurer freeMarkerConfigurer;
	@Resource private TemplateService templateService;
	
	@Resource
	public void setBaseDao(MessageSendDao messageSendDao) {
		super.setBaseDao(messageSendDao);
	}
	
	/**
	 * 根据模板名称， 路径是指定的，发送短信接口(单条发送)
	 * @param phoneNum 短信号码	
	 * @param template_name 模板名称
	 * @return 返回发送状态
	 * @throws IOException 
	 */
	@Override
	@Transactional(noRollbackFor=NoticeException.class)
	public Boolean sendMessageTemplateName(String phoneNum, String ip, Boolean isCaptcha, String template_name, Map<String, Object> map, 
			Date sendTime, MessageType type) {
		//验证码类型短信发送次数需做限制 一信通要求
		if(Boolean.TRUE.equals(isCaptcha)) {
			verifyCaptchaSMS(phoneNum, ip);
		}
		String templatePath = templateService.getTemplatePathByName(template_name);
		if(StringUtils.isBlank(templatePath)){
			return false;
		}
		if(StringUtils.isEmpty(phoneNum)){
			return false;
		}
		if(!VerifyUtil.verifyMobile(phoneNum, false)){
			return false;
		}
		if(map == null){
			map = new HashMap<String, Object>();
		}
		String content;
		try {
			Configuration configuration = freeMarkerConfigurer.getConfiguration();
			Template template = configuration.getTemplate(templatePath, "utf-8");
			content = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
		} catch (Exception e) {
			return false;
		}
		return this.sendSimpleMessage(phoneNum, content, null, type);
	}
	
	/**
	 * 发送短信接口(单条发送)
	 * @param phoneNum 短信号码	
	 * @param content 短信内容
	 * @return 返回发送状态
	 * @throws IOException 
	 */
	public Boolean sendSimpleMessage(String phoneNum, String content, Date sendTime, MessageType type) {
		String sn = SerialNumberUtil.buildSmsMessageSn();
		SmsMessageDomain message = new SmsMessageDomain();
		message.setSn(sn);//设置
		message.setType(type);
		message.setSmsNumber(phoneNum);
		if(sendTime==null){
			message.setSendTime(new Date());
		}else{
			message.setSendTime(sendTime);
		}
		message.setSmsContent(content);
		message.setStatus(MessageStatus.UNSEND);//状态未发送
		this.persist(message);
		return doSendMessage(phoneNum, content, sn, sendTime, message);
	}


/*	public static String batchSend(String url, String un, String pw, String phone, String msg,
								   String rd, String ex) throws Exception {
		HttpClient client = new HttpClient(new HttpClientParams(), new SimpleHttpConnectionManager(true));
		GetMethod method = new GetMethod();
		try {
			URI base = new URI(url, false);
			method.setURI(new URI(base, "send", false));
			method.setQueryString(new NameValuePair[] {
					new NameValuePair("un", un),
					new NameValuePair("pw", pw),
					new NameValuePair("phone", phone),
					new NameValuePair("rd", rd),
					new NameValuePair("msg", msg),
					new NameValuePair("ex", ex),
			});
			int result = client.executeMethod(method);
			if (result == HttpStatus.SC_OK) {
				InputStream in = method.getResponseBodyAsStream();
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				byte[] buffer = new byte[1024];
				int len = 0;
				while ((len = in.read(buffer)) != -1) {
					baos.write(buffer, 0, len);
				}
				return URLDecoder.decode(baos.toString(), "UTF-8");
			} else {
				throw new Exception("HTTP ERROR Status: " + method.getStatusCode() + ":" + method.getStatusText());
			}
		} finally {
			method.releaseConnection();
		}
	}*/


	/**
	 * 执行短信发送并且得到返回信息
	 * 
	 * @param phoneNum
	 *            短信号码
	 * @param content
	 *            短信内容
	 * @param SerialNumber
	 *            流水号
	 * @param ScheduleTime
	 *            发送时间
	 * @return
	 */
	public boolean doSendMessage(String phoneNum, String content,
			String SerialNumber, Date sendTime, SmsMessageDomain message) {
		String info = "";
		try {
			/*HttpClient httpclient = new HttpClient();
			String url = PropertiesHelper.getPropertiesValue("/config",
			"sms_message_sendurl");
			String SpCode = PropertiesHelper.getPropertiesValue(
					"/config", "sms_message_spcode");
			String LoginName = PropertiesHelper.getPropertiesValue(
					"/config", "sms_message_loginname");
			String password = PropertiesHelper.getPropertiesValue(
					"/config", "sms_message_password");
			PostMethod post = new PostMethod(url);// 发送地址
			post.getParams().setParameter(
					HttpMethodParams.HTTP_CONTENT_CHARSET, "gbk");
			post.addParameter("SpCode",SpCode );// SP号
			post.addParameter("LoginName", LoginName);// 登陆号
			post.addParameter("Password", password);// 登陆密码
			post.addParameter("MessageContent", content);
			post.addParameter("UserNumber", phoneNum);
			post.addParameter("SerialNumber", SerialNumber);
			if(sendTime != null){
				post.addParameter("ScheduleTime", DateHelper.date2String(sendTime, "yyyyMMddhhmmss"));
			}
			post.addParameter("f", "1");
			httpclient.executeMethod(post);
			info = new String(post.getResponseBody(), "gbk");*/


			HttpClient httpclient = new HttpClient();
			String url = PropertiesHelper.getPropertiesValue("/config",
					"sms_message_sendurl");
			String SpCode = PropertiesHelper.getPropertiesValue(
					"/config", "sms_message_spcode");
			String LoginName = PropertiesHelper.getPropertiesValue(
					"/config", "sms_message_loginname");
			String password = PropertiesHelper.getPropertiesValue(
					"/config", "sms_message_password");
			PostMethod post = new PostMethod(url);// 发送地址
			post.getParams().setParameter(
					HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
//			post.addParameter("SpCode",SpCode );// SP号
			post.addParameter("un", LoginName);// 登陆号
			post.addParameter("pw", password);// 登陆密码
			post.addParameter("msg", content);
			post.addParameter("phone", phoneNum);
			//post.addParameter("ex", SerialNumber);
			if(sendTime != null){
				post.addParameter("ScheduleTime", DateHelper.date2String(sendTime, "yyyyMMddhhmmss"));
			}
			post.addParameter("rd", "1");
			httpclient.executeMethod(post);
			info = new String(post.getResponseBody(), "UTF-8");
		} catch (Exception e) {
			return false;
		}
		boolean sendStatus = false;
		if(StringUtils.isNotEmpty(info)){
			String result = "";//返回状态值
			String description = "";//返回状态信息
			String[] infoArray = info.split(",");
			if(infoArray.length>1&&!StringUtils.isBlank(infoArray[1])){
				result = infoArray[1].split("\\n")[0];
			}
		/*	for(String item:infoArray){
				String[] items = item.split("=");
				if(items[0].equals("result")){
					result=items[1];
				}else if(items.length>1&&items[0].equals("description")){
					description=items[1];
				}
			}*/
			//发送成功
			if(StringUtils.equals(result, "0")) {
				description=infoArray[1].split("\\n")[1];
				message.setStatus(MessageStatus.SUCCESS);
				message.setDescription(description);
				sendStatus = true;
			} else {//发送不成功
				message.setStatus(MessageStatus.FIALURE);
				description=result;
				message.setDescription(description);
				sendStatus = false;
			}
			this.update(message);
		}else{
			sendStatus= false;
		}
		return sendStatus;
	}
	
//	/**
//	 * 建周短信平台
//	 * @param phoneNum 手机号码
//	 * @param content 短信内容
//	 * @param message 
//	 * @return
//	 */
//	public boolean doJzSMS(String phoneNum, String content, SmsMessageDomain message){
//		String sendUrl = PropertiesHelper.getPropertiesValue("config", "jz_sms_sendurl");
//		String account = PropertiesHelper.getPropertiesValue("config", "jz_sms_account");
//		String password = PropertiesHelper.getPropertiesValue("config", "jz_sms_password");
//		BusinessService bs = new BusinessService();
//		bs.setWebService(sendUrl);
//		int status = bs.sendBatchMessage(account, password, phoneNum, content);
//		if(status > 0){
//			message.setStatus(MessageStatus.SUCCESS);
//			message.setTaskId(status + "");
//			message.setDescription("发送短信成功");
//		}else{
//			message.setStatus(MessageStatus.FIALURE);
//			message.setDescription("");
//		}
//		this.update(message);
//		return status > 0;
//	}
	
	public boolean doXstSMS(String phoneNum, String content, Date sendTime, SmsMessageDomain message){
		String info = "";
		try {
			HttpClient httpclient = new HttpClient();
			String url = PropertiesHelper.getPropertiesValue(
					"config", "xst_sms_sendurl");
			String userid = PropertiesHelper.getPropertiesValue(
					"config", "xst_sms_userid");
			String account = PropertiesHelper.getPropertiesValue(
					"config", "xst_sms_account");
			String password = PropertiesHelper.getPropertiesValue(
					"config", "xst_sms_password");
			String action = PropertiesHelper.getPropertiesValue(
					"config", "xst_sms_action");
			PostMethod post = new PostMethod(url);// 发送地址
			post.getParams().setParameter(
					HttpMethodParams.HTTP_CONTENT_CHARSET, "utf8");
			post.addParameter("userid", userid );// SP号
			post.addParameter("account", account);// 登陆号
			post.addParameter("password", password);// 登陆密码
			post.addParameter("mobile", phoneNum);
			post.addParameter("content", content);
			post.addParameter("action", action);
			if(sendTime != null){
				post.addParameter("sendTime", DateHelper.date2String(sendTime, "yyyyMMddHHmmss"));
			}
			post.addParameter("f", "1");
			httpclient.executeMethod(post);
			info = new String(post.getResponseBody(), "utf8");
		} catch (Exception e) {
			return false;
		}
		boolean sendStatus = false;
		StringReader sr = new StringReader(info);
		SAXReader saxReader = new SAXReader();
		try {
			Document doc = saxReader.read(sr);
			Element root = doc.getRootElement();
			String returnstatus = root.element("returnstatus").getStringValue();
			String returnMessage = root.element("message").getStringValue();
			String taskID = root.element("taskID").getStringValue();
			if("Success".equals(returnstatus)){
				message.setStatus(MessageStatus.SUCCESS);
				message.setTaskId(taskID);
				message.setDescription("发送短信成功");
				sendStatus = true;
			}else{
				message.setStatus(MessageStatus.FIALURE);
				message.setDescription(returnMessage);
				sendStatus = false;
			}
			this.update(message);
		} catch (DocumentException e) {
			return false;
		}
		return sendStatus;
	}

	public void verifyCaptchaSMS(String mobile, String ip) {
		if(StringUtils.isBlank(mobile)) {
			throw new NoticeException("验证码短信, 手机号码不能为空!");
		}
		if(StringUtils.isBlank(ip)) {
			throw new NoticeException("验证码短信, 用户IP不能为空!");
		}
		/**24小时内，同一个手机号码限制*/
		Date yesterdayNow = DateUtils.addDays(new Date(), -1);
		Finder finder = Finder.create("select count(bean) from SmsMessageDomain bean where 1=1");
		finder.append(" and bean.smsNumber = :mobile").setParam("mobile", mobile);
		finder.append(" and bean.type = :type").setParam("type", MessageType.mobileVerify);
		finder.append(" and bean.createDate > :yesterdayNow").setParam("yesterdayNow", yesterdayNow);
		if((Long)finder.findUniqueByHQL() >= CAPTCHA_MOBILE_LIMIT) {
			throw new NoticeException("验证码短信发送过于频繁!");
		}
		/**24小时内，同一个IP限制*/
		finder = Finder.create("select count(bean) from SmsMessageDomain bean where 1=1");
		finder.append(" and bean.ip = :ip").setParam("ip", ip);
		finder.append(" and bean.type = :type").setParam("type", MessageType.mobileVerify);
		finder.append(" and bean.createDate > :yesterdayNow").setParam("yesterdayNow", yesterdayNow);
		if((Long)finder.findUniqueByHQL() >= CAPTCHA_IP_LIMIT) {
			throw new NoticeException("验证码短信发送过于频繁!");
		}
	}
}